package xiaomi

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"dta-apk/global"
	"dta-apk/utils"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"os"
	"path/filepath"
)

const KEY_SIZE = 1024
const GROUP_SIZE = KEY_SIZE / 8
const ENCRYPT_GROUP_SIZE = GROUP_SIZE - 11
const CERT_FILE_PATH = "dev.api.public.cer"

/*
签名

参数：
  - param 普通参数集合
  - fileParam 文件md5参数集合 {"name": "HashMd5"}
*/
func sign(param map[string]string, fileParam map[string]string) (string, error) {
	// 参数数据格式 {"name":"parameterName1"，"hash":"MD5(parameterValue1)"}
	paramJson, error := json.Marshal(param)
	if error != nil {
		panic(error)
	}
	var signItems []interface{}
	// 参数的md5
	signItem := map[string]string{
		"name": "RequestData",
		"hash": utils.GetStringMd5(string(paramJson)),
	}
	signItems = append(signItems, signItem)
	// 如果有文件，合并文件的md5
	for k, v := range fileParam {
		signItem := map[string]string{
			"name": k,
			"hash": v,
		}
		signItems = append(signItems, signItem)
	}

	sig := map[string]interface{}{
		"password": global.Config.App.XiaoMi.UserPass,
		"sig":      signItems,
	}

	// 转数据类型
	sigJson, _ := json.Marshal(sig)
	// 加载公钥证书
	publicKey, error := loadPublicKeyFromCert()
	if error != nil {
		fmt.Println(error.Error())
		return "", error
	}

	// 数字签名
	sign, error := encryptByPublicKey(sigJson, publicKey)

	if error != nil {
		return "", error
	}
	return sign, nil

}

// 加载公钥
func loadPublicKeyFromCert() (*rsa.PublicKey, error) {
	// 读取公钥文件
	certData, err := os.ReadFile(getPublickeyFile())
	if err != nil {
		return nil, err
	}
	block, _ := pem.Decode(certData)
	if block == nil {
		return nil, fmt.Errorf("failed to parse certificate PEM data")
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, err
	}
	publicKey, ok := cert.PublicKey.(*rsa.PublicKey)
	if !ok {
		return nil, fmt.Errorf("invalid public key type")
	}
	return publicKey, nil
}

// PKCS1 加密
func encryptByPublicKey(plaintext []byte, publicKey *rsa.PublicKey) (string, error) {
	encryptedData := make([]byte, 0)
	for len(plaintext) > 0 {
		var blockSize int
		if len(plaintext) > ENCRYPT_GROUP_SIZE {
			blockSize = ENCRYPT_GROUP_SIZE
		} else {
			blockSize = len(plaintext)
		}
		encryptedBlock, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plaintext[:blockSize])
		if err != nil {
			return "", err
		}
		encryptedData = append(encryptedData, encryptedBlock...)
		plaintext = plaintext[blockSize:]
	}

	return fmt.Sprintf("%x\n", encryptedData), nil
}

// 拼接请求接口地址
func getApiUrl(api string) string {
	return domain_url + api
}

// 公钥文件地址
func getPublickeyFile() string {
	currentDir, err := os.Getwd()
	if err != nil {
		return ""
	}
	return filepath.Join(currentDir, "resource", CERT_FILE_PATH)
}

// 请求表头
func getHeaders() map[string]string {
	headers := map[string]string{
		"Content-Type": "application/json; charset=UTF-8",
	}
	return headers
}
